package com.whitecat.voting.util;

import com.whitecat.voting.exception.BusinessException;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.FrameGrabber;
import org.bytedeco.javacv.Java2DFrameConverter;

import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.io.File;
import java.io.IOException;

public class MaterialUtils {

    /**
     * 获取视频时长（单位：秒）
     */
    public static long getVideoDuration(File video) {
        long duration = 0L;
        FFmpegFrameGrabber ff = new FFmpegFrameGrabber(video);
        try {
            ff.start();
            duration = ff.getLengthInTime() / (1000 * 1000);
            ff.stop();
        } catch (FrameGrabber.Exception e) {
            e.printStackTrace();
        }
        return duration;
    }

    /**
     * 提取封面
     */
    public static File extractScreenshot(File videoFile) {
        File output = FileUtils.getFile(videoFile.getParentFile(), "screenshot.jpeg");
        FFmpegFrameGrabber ff;
        try {
            ff = FFmpegFrameGrabber.createDefault(videoFile);
        } catch (FrameGrabber.Exception e) {
            throw new BusinessException("Occurring an exception during video reading!", e);
        }

        try {
            ff.start();
        } catch (FrameGrabber.Exception e) {
            throw new BusinessException("Occurring an exception during grabbing starting!", e);
        }

        int ffLength = ff.getLengthInFrames();
        Frame f;
        int i = 0;
        while (i < ffLength) {
            try {
                f = ff.grabImage();
            } catch (FrameGrabber.Exception e) {
                throw new BusinessException("Occurring an exception during video grabbing!", e);
            }

            // 截取第6帧
            if ((i > 5) && (f.image != null)) {
                Java2DFrameConverter converter = new Java2DFrameConverter();
                BufferedImage bi = converter.getBufferedImage(f);

                try {
                    ImageIO.write(bi, "jpeg", output);
                } catch (IOException e) {
                    throw new BusinessException("Occurring an exception during image generating!", e);
                }

                break;
            }
            i++;
        }
        try {
            ff.stop();
        } catch (FrameGrabber.Exception e) {
            throw new BusinessException("Occurring an exception during grabbing ending!", e);
        }

        return output;
    }

    /**
     * 等比例压缩图片
     */
    public static void compressImage(File imgFile) {
        BufferedImage src;
        try {
            src = ImageIO.read(imgFile);
        } catch (IOException e) {
            throw new BusinessException("Occurring an exception during image reading!", e);
        }

        ImageWriteParam imgWriteParams = new javax.imageio.plugins.jpeg.JPEGImageWriteParam(null);
        imgWriteParams.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
        imgWriteParams.setCompressionQuality((float) 0.5); // 取值范围：0~1
        imgWriteParams.setProgressiveMode(ImageWriteParam.MODE_DISABLED);
        ColorModel colorModel;
        try {
            colorModel = ImageIO.read(imgFile).getColorModel();
        } catch (IOException e) {
            throw new BusinessException("Occurring an exception during image color model reading!", e);
        }
        imgWriteParams.setDestinationType(new javax.imageio.ImageTypeSpecifier(colorModel, colorModel.createCompatibleSampleModel(16, 16)));

        ImageWriter imgWriter = ImageIO.getImageWritersByFormatName("jpeg").next();
        imgWriter.reset();
        String imgFileName = imgFile.getName();
        File newImg = FileUtils.getFile(imgFile.getParent(), FilenameUtils.getBaseName(imgFileName) + "__compress." + FilenameUtils.getExtension(imgFileName));
        try {
            imgWriter.setOutput(ImageIO.createImageOutputStream(FileUtils.openOutputStream(newImg)));
            imgWriter.write(null, new IIOImage(src, null, null), imgWriteParams);
        } catch (IOException e) {
            throw new BusinessException("Occurring an exception during image writing!", e);
        }
    }

    /**
     * 按比例缩放图片
     *
     * @return
     */
    public static File scaleImage(File imgFile, double scale) {

        BufferedImage bufferedImage;
        try {
            bufferedImage = ImageIO.read(imgFile);
        } catch (IOException e) {
            throw new BusinessException("Occurring an exception during image reading!", e);
        }

        if (bufferedImage == null) {
            throw new BusinessException("Image " + imgFile.getAbsolutePath() + " is unavailable!");
        }

        int width = bufferedImage.getWidth();
        int height = bufferedImage.getHeight();

        width = (int) (width * scale);
        height = (int) (height * scale);

        Image image = bufferedImage.getScaledInstance(width, height, Image.SCALE_SMOOTH);
        BufferedImage outputImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics graphics = outputImage.getGraphics();
        graphics.drawImage(image, 0, 0, null);
        graphics.dispose();

        File parentDir = imgFile.getParentFile();
        String fn = imgFile.getName();
        String format = FilenameUtils.getExtension(fn);

        File targetImg = FileUtils.getFile(parentDir, "thumb." + format);
        try {
            ImageIO.write(outputImage, format, targetImg);
        } catch (IOException e) {
            throw new BusinessException("Occurring an exception during image writing!", e);
        }

        return targetImg;
    }
}
